package Objects;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class RoutingTable {
	String myID;
	char myIG;
	Set<String> myIntraRouters;
	ConcurrentHashMap<String, PathInfo> destination;

	public RoutingTable() {
		myID = "";
		myIG = 'z';
		myIntraRouters = new HashSet<String>();
		destination = new ConcurrentHashMap<String, PathInfo>();
	}

	public String getMyID() {
		return myID;
	}

	public void setMyID(String myID) {
		this.myID = myID;
	}

	public char getMyIG() {
		return myIG;
	}

	public void setMyIG(char myIG) {
		this.myIG = myIG;
	}

	public Set<String> getIntraRouters() {
		return myIntraRouters;
	}

	public void setIntraRouters(HashSet<String> myIntraRouters) {
		this.myIntraRouters = myIntraRouters;
	}

	public ConcurrentHashMap<String, PathInfo> getDestination() {
		return destination;
	}

	public void setDestination(ConcurrentHashMap<String, PathInfo> destination) {
		this.destination = destination;
	}

	public void addIntraRouter(String intraRouter) {
		myIntraRouters.add(intraRouter);
	}

	public void removeIntraRouter(String intraRouter) {
		myIntraRouters.remove(intraRouter);
	}

	public String printMyIntraRouters() {
		String returnString = "";
		Iterator<String> it = myIntraRouters.iterator();
		while (it.hasNext()) {
			returnString += it.next() + ", ";
		}
		returnString = returnString.substring(0, returnString.length() - 2);
		return returnString;
	}

	public String getNextHop(String destination) {
		// try to figure out my next hop
		// if im intra router, then the next hop should be in my map,
		// if its not in my map, then set the destination to my gateway router
		if (myIG == 'i') {
			if (this.destination.containsKey(destination))
				return this.destination.get(destination).getNextHop();
			else {
				String myGateWayRouter = getMyGateWayRouter();
				if (myGateWayRouter.equals("")) {
					return "";
				} else
					return this.destination.get(myGateWayRouter).getNextHop();
			}
		} else {
			if (this.destination.containsKey(destination))
				return this.destination.get(destination).getNextHop();
			else {
				String destinationGateWay = "";
				Iterator<String> it = this.destination.keySet().iterator();
				while (it.hasNext()) {
					String tempDestination = it.next();
					// Logger.log(Logger.DEBUG,
					// "Do other gateway has the destination: "
					// +
					// this.destination.get(tempDestination).hasIntaRouter(destination));
					if (this.destination.get(tempDestination).hasIntaRouter(destination)) {
						destinationGateWay = tempDestination;
						break;
					}
				}
				if (!destinationGateWay.equals(""))
					return this.destination.get(destinationGateWay).getNextHop();
				else
					return "";
			}
		}
	}

	public boolean routerPurged(String deadRouter, char deadRouterIG) {
		// try to figure out if the dead router is purged already
		if (myIG == 'i') {
			return !destination.containsKey(deadRouter);
		} else {
			if (deadRouterIG == 'i') {
				if (isIntraPurgedFromInterNeighbors(deadRouter) && !destination.containsKey(deadRouter))
					return true;
				else
					return false;
			} else {
				return !destination.containsKey(deadRouter);
			}
		}
	}

	private String getMyGateWayRouter() {
		String myGateWayRouter = "";
		Iterator<String> it = destination.keySet().iterator();
		while (it.hasNext()) {
			String destinationID = it.next();
			if (destination.get(destinationID).getIG() == 'g') {
				myGateWayRouter = destinationID;
				break;
			}
		}
		return myGateWayRouter;
	}

	private boolean isIntraPurgedFromInterNeighbors(String intraID) {
		Iterator<String> it = destination.keySet().iterator();
		while (it.hasNext()) {
			String destinationID = it.next();
			if (destination.get(destinationID).getIntraRouters().contains(intraID)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public String toString() {
		String routingTable = "";
		routingTable += "Routing Table for " + myID + "\n";
		if (myIG == 'g') {
			routingTable += "My intra router: " + printMyIntraRouters() + "\n";
		}
		routingTable += "-------------------------------------------\n";
		Iterator<String> it = destination.keySet().iterator();
		while (it.hasNext()) {
			routingTable += destination.get(it.next()).toString();
		}
		return routingTable;
	}
}
